home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
kcl.lha
/
c
/
dguxsave.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-04
|
7KB
|
285 lines
/*
(C) Copyright Taiichi Yuasa and Masami Hagiya, 1984. All rights reserved.
*/
#include "include.h"
struct nsection {
unsigned int logical_start;
unsigned int logical_length;
unsigned int file_start;
unsigned int file_length;
unsigned int file_reloc;
unsigned int file_reloc_length;
unsigned int attributes;
};
struct prformat {
unsigned short magic_number; /* magic */
unsigned short format_rev_number; /* format rev. number */
unsigned short num_non_exec_sect; /* # of non-exec. sects */
unsigned short num_exec_sect; /* # of executable sects */
struct nsection syshead; /* system header */
struct nsection symbolt; /* symbol table */
struct nsection ds; /* */
struct nsection dl; /* */
struct nsection lt; /* */
struct nsection exec[2]; /* two executable sections */
};
struct system_header {
unsigned int start_pc;
unsigned int stacks;
unsigned int unlabeled;
unsigned int time_stamp;
unsigned int user_rev_number;
unsigned short flags;
unsigned short ntasks;
unsigned short nchannels;
};
struct stack_register {
unsigned int fp;
unsigned int sp;
unsigned int sl;
unsigned int sb;
};
#define NUM_ENVIRON 6
/*
saved_init copies arg and environment variables from top of data
segment to stack area and shrink the memory.
When execed by system, arg and environment variables are as follows;
break value --> | |
+--------------------+
| environ array ptr |--------+
+--------------------+ |
| argument array ptr |----+ |
+--------------------+ | |
AC2 ----------> | argument count | | |
+--------------------+ | |
| | | |
+============> | environment | | |
! | | | |
! +--------------------+ | |
! | | | |
! +====> | arguments | | |
! ! | | | |
! ! +--------------------+ | |
+====== ! ===== | environment array |<-- | --+
! +--------------------+ |
+====== | argument array |<---+
+--------------------+
| |
*/
void
saved_init()
{
char *break_value;
char *new_break_value;
char *sbrk();
char *old_start; /* old data area start byte address */
char *new_start; /* new data area start byte address */
int size; /* data size */
int *sp; /* wide stack pointer */
int i;
int argc;
char **argv;
char **envp;
break_value = sbrk(0);
argc = *((unsigned int *)break_value - 3); /* arg count */
argv =
(char **)(*((unsigned int *)break_value - 2)); /* arg array ptr */
envp =
(char **)(*((unsigned int *)break_value - 1)); /* env array ptr */
/*
old_start will be new break value after initialization.
*/
new_break_value = old_start = (char *)&argv[0];
/*
calc total space required. size is byte size and is multiple of 4
becase both break_value and argv[0] are double word boundary.
*/
size = break_value - old_start;
/* allocate space from stack. */
sp = getsp(); /* current stack pointer */
setsp(sp + size / 4); /* extent stack */
new_start = (char *)(sp + 1);
blockmove(new_start, old_start, size);
/*
set up new argv and new envp
*/
argv = ((unsigned int)argv - (old_start - new_start) / 2);
envp = ((unsigned int)envp - (old_start - new_start) / 2);
for (i = 0; i < argc; i++)
argv[i] -= (old_start - new_start);
for (i = 0; i < NUM_ENVIRON; i++)
envp[i] -= (old_start - new_start);
new_break_value =
(((unsigned int)new_break_value + PAGESIZE -1 ) / PAGESIZE) * PAGESIZE;
brk(new_break_value); /* shrink memory */
main(argc, argv, envp); /* call main routine */
exit(0);
}
filecpy(to, from, n)
FILE *to, *from;
int n;
{
char buffer[BUFSIZ];
for (;;)
if (n > BUFSIZ) {
fread(buffer, BUFSIZ, 1, from);
fwrite(buffer, BUFSIZ, 1, to);
n -= BUFSIZ;
} else if (n > 0) {
fread(buffer, n, 1, from);
fwrite(buffer, n, 1, to);
break;
} else
break;
}
memory_save(original_file, save_file)
char *original_file, *save_file;
{
int s, n;
char *data_start;
int data_size;
int orig_e0_start, orig_e0_len, orig_e1_start, orig_e1_len;
char *p, *sbrk();
void SVINIT(); /* special initializer */
FILE *in, *out;
struct prformat head;
struct system_header system;
struct stack_register sregs;
char buffer0[BUFSIZ], buffer1[BUFSIZ];
char buffer[BUFSIZ];
out = fopen(save_file, "w+");
if (out == NULL) FEerror("Can't open output file.", 0);
setbuf(out, buffer0);
in = fopen(original_file, "r");
if (in == NULL) FEerror("Can't open original KCl.", 0);
setbuf(in, buffer1);
/*
First, we must build file header. File header is built
by modifying the origial program's file header.
*/
fread((char *)&head, sizeof(struct prformat), 1, in);
orig_e0_start = head.exec[0].file_start;
orig_e0_len = head.exec[0].file_length;
orig_e1_start = head.exec[1].file_start;
orig_e1_len = head.exec[1].file_length;
data_size = sbrk(0) - (char *)034000000000;
head.exec[1].file_start = (orig_e0_start + data_size + 02000) & ~01777;
s = head.exec[1].file_start - orig_e1_start;
head.symbolt.file_start += s;
head.ds.file_start += s;
head.dl.file_start += s;
head.lt.file_start += s;
head.exec[0].logical_length += (s / 2);
head.exec[0].file_length = data_size;
fwrite((char *)&head, sizeof(struct prformat), 1, out); /* header */
/*
Start_pc should be changed to special initializer for
a saved program.
*/
fread((char *)&system, sizeof(system), 1, in);
system.start_pc = &SVINIT;
system.stacks = *(unsigned int *)016000000024 -
*(unsigned int *)016000000026;
fwrite((char *)&system, sizeof(system), 1, out);
/*
gap
*/
filecpy(out, in, orig_e0_start - sizeof(struct prformat)
- sizeof(struct system_header));
/*
data segment
*/
for (p = (char *)034000000000, n = data_size;
;p += BUFSIZ, n -= BUFSIZ)
if (n > BUFSIZ)
fwrite(p, BUFSIZ, 1, out);
else if (n > 0) {
fwrite(p, n, 1, out);
break;
} else
break;
/*
gap
*/
zero(buffer, BUFSIZ);
fwrite(buffer,
head.exec[1].file_start - (head.exec[0].file_start + data_size),
1,
out);
/*
text segment
*/
fseek(in, orig_e1_start, 0);
filecpy(out, in, head.exec[1].file_length);
/*
others
*/
filecpy(out, in, head.symbolt.file_length);
filecpy(out, in, head.ds.file_length);
filecpy(out, in, head.dl.file_length);
filecpy(out, in, head.lt.file_length);
fclose(out);
fclose(in);
chmod(save_file, 0777); /* change file mode */
}
Lsave()
{
char filename[256];
check_arg(1);
check_type_or_pathname_string_symbol_stream(&vs_base[0]);
coerce_to_filename(vs_base[0], filename);
memory_save(kcl_self, filename);
exit(0);
}
init_dguxsave()
{
make_function("SAVE", Lsave);
}